package com.xuyu.common.tool.excel;



import com.alibaba.excel.EasyExcel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

@Slf4j
public class ExcelCore {

    private static final String EXCEL_SUFFIX = ".xlsx";


    /**
     * 处理excel即时导出
     * @param getData 获得数据
     * @param template 模板
     * @param fileName 文件名
     */
    public static void export(Supplier<Collection<?>> getData, TemplateFactory template, String fileName, HttpServletResponse response) {
        exportByTemplate(getData.get(), template, fileName, response);
    }

    /**
     * 处理excel即时导出
     * @param data 原始数据
     * @param template 模板
     * @param fileName 文件名
     */
    public static void exportByTemplate(Collection<?> data, TemplateFactory template, String fileName, HttpServletResponse response) {
        Assert.notNull(template, "模板不能为空");
        ExcelTemplate[] content = template.getContent();
        List<List<Object>> allExcelData = new ArrayList<>();
        Object firstExample = data.iterator().next();
        for (Object o : data) {
            List<Object> excelData = getExcelData(o, content);
            allExcelData.add(excelData);
        }
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileNameUse = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileNameUse + ".xlsx");
            EasyExcel.write(response.getOutputStream()).head(getHead(content, firstExample)).sheet(fileName).doWrite(allExcelData);
        } catch (IOException e) {
            log.error("打出异常", e);
            throw new RuntimeException("导出异常", e);
        }
    }


    private static String handFileName(String fileName) {
        return fileName + EXCEL_SUFFIX;
    }

    /**
     * 获得excel头
     * @param param 需要传入一条数据进来进行表头的运算
     */
    private static List<List<String>> getHead(ExcelTemplate[] content, Object param) {
        List<List<String>> head = new ArrayList<>();
        for (ExcelTemplate c : content) {
            Predicate<Object> condition = c.condition();
            if (!condition.test(param)) {
                //不需要这个字段
                continue;
            }
            List<String> temp = new ArrayList<>();
            temp.add(c.getColumn());
            head.add(temp);
        }
        return head;
    }

    /**
     * 构建excel数据
     * @param o 原始值对象
     * @param content 模板内容
     * @return 数据
     */
    private static List<Object> getExcelData(Object o, ExcelTemplate[] content) {
        List<Object> list = new ArrayList<>();
        for(ExcelTemplate e : content) {
            if (!e.condition().test(o)) {
                //不需要这个字段
                continue;
            }
            Function<Object, Object> value = e.getValue();
            Object apply = value.apply(o);
            //注意 easyExcel遇到某些字段的时候，无法正常转换，此时要把数据类型转一下！
            if (apply instanceof LocalDate) {
                list.add(apply.toString());
            } else {
                list.add(apply);
            }
        }
        return list;
    }
}
